/*
 * =====================================================================================
 *
 *       Filename:  socker.cpp
 *
 *    Description:  
 *
 *        Version:  1.0
 *        Created:  17.05.2012 21:52:04
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  YOUR NAME (), 
 *   Organization:  
 *
 * =====================================================================================
 */
#include "sslsocket.hpp"

namespace Drosera {

bool SSLSocket::m_status = false;

SSLSocket::SSLSocket ( SSL *ssl ) {
	m_ctx = NULL;
	m_ssl = ssl;
	setSocket ( SSL_get_fd ( ssl ) );
}

SSLSocket::~SSLSocket ( void ) {
	if ( m_ssl != NULL ) SSL_free ( m_ssl );
	if ( m_ctx != NULL ) SSL_CTX_free ( m_ctx );
}

SSL_CTX *SSLSocket::getCTX ( void ) {
	return m_ctx;
}

SSLSocket::SSLSocket ( void ) {
}

// Init Serverdata and WSA
bool SSLSocket::initSocket ( const char *cert_pub, const char *cert_pri ) {

	m_ssl = NULL;
	m_ctx = NULL;

	if ( m_status == false ) {
		SSL_library_init();
		CRYPTO_malloc_init();
		OpenSSL_add_all_algorithms();
		SSL_load_error_strings();
		m_status = true;
	}
	
	const SSL_METHOD *method;
	method = SSLv23_server_method();
	m_ctx = SSL_CTX_new ( method );

	if ( m_ctx == NULL ) return false;
	// if ( SSL_CTX_set_default_passwd_cb ( m_ctx, pwd ) <= 0 ) return false;
	if ( SSL_CTX_use_certificate_file ( m_ctx, cert_pub, SSL_FILETYPE_PEM ) <= 0 ) return false;
	if ( SSL_CTX_use_PrivateKey_file ( m_ctx, cert_pri, SSL_FILETYPE_PEM ) <= 0 ) return false;
	if ( !SSL_CTX_check_private_key ( m_ctx ) ) return false;

	return true;
}


// Accept a new incomming Socket ( Server Side )
int SSLSocket::sslacceptSocket ( SOCKET in_sock, SSL *ssl ) {

	SOCKET new_sock = acceptSocket ( in_sock );

	if ( new_sock < 0 ) return -1;

	SSL_set_fd ( ssl, new_sock );

	if ( SSL_accept ( ssl ) == -1 )
		return -1;

	return 0;
}


// Send data throug the Socket
bool SSLSocket::sendSocket ( std::string& data ) {

	int status = SSL_write ( m_ssl, (unsigned char*) data.c_str(), data.size() );

	if ( status <= 0) return false;

	return true;
}

// Recive data from Socket
int SSLSocket::recvSocket ( std::string &buf ) {
	
	char data[ MAXRECV + 1 ];
	memset ( data, 0, MAXRECV + 1 );
	ssize_t size = SSL_read ( m_ssl, (unsigned char*) data, MAXRECV + 1 );
	
	if ( buf.size() ) buf.clear();
	buf.append ( data, size);
	return 0;
}


void SSLSocket::setSSL ( SSL *ssl ) {
	m_ssl = ssl;
}

}
